package me.sealer.ssm.service.impl;

import com.github.pagehelper.PageHelper;
import lombok.extern.slf4j.Slf4j;
import me.sealer.ssm.constant.ErrorCodeConstant;
import me.sealer.ssm.constant.PageConstant;
import me.sealer.ssm.exception.SsmException;
import me.sealer.ssm.mapper.RoleMapper;
import me.sealer.ssm.mapper.RoleMenuMapper;
import me.sealer.ssm.mapper.RolePermissionMapper;
import me.sealer.ssm.mapper.UserMapper;
import me.sealer.ssm.mapper.UserRoleMapper;
import me.sealer.ssm.model.Role;
import me.sealer.ssm.model.RoleExample;
import me.sealer.ssm.model.RoleMenu;
import me.sealer.ssm.model.RoleMenuExample;
import me.sealer.ssm.model.RolePermission;
import me.sealer.ssm.model.User;
import me.sealer.ssm.page.PageResult;
import me.sealer.ssm.service.RoleService;
import me.sealer.ssm.utils.PageUtil;
import me.sealer.ssm.utils.StringUtil;
import org.apache.shiro.util.Assert;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

/**
 * @author sealer
 * @date 2018/05/11.
 */
@Slf4j
@Service
public class RoleServiceImpl implements RoleService {
    private final RoleMapper roleMapper;
    private final UserMapper userMapper;
    private final UserRoleMapper userRoleMapper;
    private final RolePermissionMapper rolePermissionMapper;
    private final RoleMenuMapper roleMenuMapper;

    public RoleServiceImpl(RoleMapper roleMapper, UserMapper userMapper, UserRoleMapper userRoleMapper, RolePermissionMapper rolePermissionMapper, RoleMenuMapper roleMenuMapper) {
        this.roleMapper = roleMapper;
        this.userMapper = userMapper;
        this.userRoleMapper = userRoleMapper;
        this.rolePermissionMapper = rolePermissionMapper;
        this.roleMenuMapper = roleMenuMapper;
    }

    @Override
    public List<Role> queryAllRoles() {
        return roleMapper.selectByExample(null);
    }

    @Override
    public Role queryRoleByRoleName(String roleName) {
        RoleExample roleExample = new RoleExample();
        roleExample.createCriteria().andNameEqualTo(roleName);

        List<Role> roles = roleMapper.selectByExample(roleExample);

        // roleName对应的Role有且只有一条
        Assert.isTrue(roles.size() == 1, "脏数据异常");

        return roles.get(0);
    }

    @Override
    public PageResult<Role> queryRolesPage(String roleName, int pageNo, int pageSize) {
        pageSize = Math.min(pageSize, PageConstant.MAX_PAGE_SIZE);

        RoleExample roleExample = generateExampleIfNonNull(roleName);

        int count = roleMapper.countByExample(roleExample);

        PageHelper.startPage(pageNo, pageSize);
        List<Role> roles = roleMapper.selectByExample(roleExample);

        return PageUtil.generatePageResult(pageNo, pageSize, roles, count);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void newRole(String name, String description, List<Integer> permissions, List<Integer> menus) {
        // add role
        Role role = Role.builder()
                .name(name)
                .description(description)
                .build();

        RoleExample roleExample = new RoleExample();
        roleExample.createCriteria().andNameEqualTo(name);
        int count = roleMapper.countByExample(roleExample);
        if (count > 0) {
            throw new SsmException(ErrorCodeConstant.ROLE_ROLE_EXISTS);
        }

        roleMapper.insertOne(role);

        // select role id from added just now
        List<Role> roles = roleMapper.selectByExample(generateExampleIfNonNull(name));
        // 有且仅有一个
        Assert.isTrue(roles.size() == 1, "脏数据异常");
        int roleId = roles.get(0).getId();

        // 添加角色权限列表
        permissions.parallelStream().forEach(pid -> rolePermissionMapper.insert(RolePermission.builder().permissionId(pid).roleId(roleId).build()));

        // 添加角色菜单列表
        menus.parallelStream().forEach(mid -> roleMenuMapper.insert(RoleMenu.builder().roleId(roleId).menuId(mid).build()));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteRole(Integer id, String name) {
        RoleExample roleExample = new RoleExample();
        roleExample.createCriteria().andIdEqualTo(id).andNameEqualTo(name);

        int count = roleMapper.countByExample(roleExample);
        if (count == 0) {
            throw new SsmException(ErrorCodeConstant.ROLE_ROLE_NOT_EXISTS);
        }

        // 查看角色是否被用户关联
        int userRoleCount = userRoleMapper.countByRoleId(id);
        if (userRoleCount > 0) {
            throw new SsmException(ErrorCodeConstant.ROLE_ROLE_BE_USED_BY_USER);
        }

        // 删除role_permission
        rolePermissionMapper.deleteByRoleId(id);

        // 删除role_menu
        RoleMenuExample roleMenuExample = new RoleMenuExample();
        roleMenuExample.createCriteria().andRoleIdEqualTo(id);
        roleMenuMapper.deleteByExample(roleMenuExample);

        // 删除role
        roleMapper.deleteByPrimary(id);
    }

    private RoleExample generateExampleIfNonNull(String roleName) {
        RoleExample roleExample = new RoleExample();
        RoleExample.Criteria criteria = roleExample.createCriteria();
        if (!StringUtil.isNullOrEmpty(roleName)) {
            criteria.andNameLike("%" + roleName + "%");
        }

        return roleExample;
    }
}
